#include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>

// 使用标准 long long 类型，并定义常量
using ll = long long;
const int MOD = 998244353;
const int MAXN = 5005;

// 预计算2的幂，用于快速得到子集总数
ll p2[MAXN];

void precompute_powers(int n) {
    p2[0] = 1;
    for (int i = 1; i <= n; ++i) {
        p2[i] = (p2[i - 1] * 2) % MOD;
    }
}

int main() {
    // OI/ACM 风格的快速输入输出
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n;
    std::cin >> n;

    std::vector<int> a(n);
    int total_sum = 0;
    for (int i = 0; i < n; ++i) {
        std::cin >> a[i];
        total_sum += a[i];
    }

    // 1. 排序：这是算法的关键前提
    std::sort(a.begin(), a.end());
    
    // 预计算2的幂
    precompute_powers(n);

    // 2. DP 数组设置
    // dp[j] 表示从当前已处理的木棍中选出若干根，使其和为 j 的方案数。
    // 背包容量上界是所有木棍的总和。
    std::vector<ll> dp(total_sum + 1, 0);
    dp[0] = 1; // 和为0的方案只有一种：不选任何木棍

    ll totans = 0;
    int cursum = 0; // 记录当前处理过的木棍的总和，作为DP容量的上界

    // 3. 主循环：依次处理每根木棍
    for (int i = 0; i < n; ++i) {
        // a[i] 是当前木棍的长度
        
        // 3.1 统计答案：
        // 假设 a[i] 是最长边，从前面的 a[0]...a[i-1] 中选边。
        // 此时 dp 数组存储的是从 {a[0], ..., a[i-1]} 中选择的方案。
        // 我们需要找到满足 sum(S) > a[i] 的子集 S 的数量。
        
        // 计算 sum(S) <= a[i] 的方案数
        ll nans = 0;
        // 注意 j 的上界是 cursum 和 a[i] 的较小值
        for (int j = 0; j <= std::min(cursum, a[i]); ++j) {
            nans = (nans + dp[j]) % MOD;
        }

        // 从 {a[0], ..., a[i-1]} 中选子集，总方案数是 2^i
        ll totpre = p2[i];
        
        // 合法方案数 = 总方案数 - 不合法方案数 (sum(S) <= a[i])
        ll ok = (totpre - nans + MOD) % MOD;
        
        // 累加到最终答案
        totans = (totans + ok) % MOD;
        
        // 3.2 更新DP数组
        // 将 a[i] 加入可选木棍池，为后续 a[i+1], a[i+2]... 作为最长边时做准备。
        cursum += a[i];
        // 0/1 背包，必须逆序遍历以保证每个物品只被选一次
        for (int j = cursum; j >= a[i]; --j) {
            dp[j] = (dp[j] + dp[j - a[i]]) % MOD;
        }
    }

    std::cout << totans << std::endl;
}
